package com.qiguliuxing.dts.merchant.config;

import com.qiguliuxing.dts.merchant.shiro.MerchantAuthorizingRealm;
import com.qiguliuxing.dts.merchant.shiro.MerchantWebSessionManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.crazycake.shiro.RedisCacheManager;
import org.crazycake.shiro.RedisManager;
import org.crazycake.shiro.RedisSessionDAO;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn;

import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
public class ShiroConfig {

	@Value("${spring.redis.host}")
	private String redisHost;

	@Value("${spring.redis.port}")
	private String redisPort;

	@Value("${spring.redis.password}")
	private String redisPassword;

	@Bean
	public Realm realm() {
		return new MerchantAuthorizingRealm();
	}

	@Bean
	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
		ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
		shiroFilterFactoryBean.setSecurityManager(securityManager);
		Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
		filterChainDefinitionMap.put("/merchant/auth/login", "anon");
		filterChainDefinitionMap.put("/merchant/auth/captchaImage", "anon");
		filterChainDefinitionMap.put("/merchant/auth/401", "anon");
		filterChainDefinitionMap.put("/merchant/auth/index", "anon");
		filterChainDefinitionMap.put("/merchant/auth/403", "anon");
		filterChainDefinitionMap.put("/merchant/storage/merchantPicUpload", "anon");
		filterChainDefinitionMap.put("/merchant/apply/commit", "anon");
		filterChainDefinitionMap.put("/merchant/apply/merchantClass", "anon");
		filterChainDefinitionMap.put("/merchant/apply/applyConfig", "anon");

		filterChainDefinitionMap.put("/merchant/**", "authc");
		shiroFilterFactoryBean.setLoginUrl("/merchant/auth/401");
		shiroFilterFactoryBean.setSuccessUrl("/merchant/auth/index");
		shiroFilterFactoryBean.setUnauthorizedUrl("/merchant/auth/403");
		shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
		return shiroFilterFactoryBean;
	}

	/**
	 * 配置shiro redisManager
	 * 使用的是shiro-redis开源插件
	 * @return
	 */
	@Bean
	public RedisManager redisManager() {
		RedisManager redisManager = new RedisManager();
		String host = redisHost + ":" + redisPort;
		redisManager.setHost(host);
		String password = StringUtils.isBlank(redisPassword) ? null : redisPassword;
		redisManager.setPassword(password);
		return redisManager;
	}

	@Bean
	public RedisSessionDAO redisSessionDAO(RedisManager redisManager) {
		RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
		redisSessionDAO.setRedisManager(redisManager);
		return redisSessionDAO;
	}

	@Bean
	public RedisCacheManager redisCacheManager(RedisManager redisManager) {
		RedisCacheManager redisCacheManager = new RedisCacheManager();
		redisCacheManager.setRedisManager(redisManager);
		return redisCacheManager;
	}

	/**
	 * shiro session 管理
	 * @return
	 */
	@Bean
	public SessionManager sessionManager(RedisSessionDAO redisSessionDAO) {
		MerchantWebSessionManager mySessionManager = new MerchantWebSessionManager();
		// 这里可以调整默认继承的shiro底层的session过期时间
		// mySessionManager.setGlobalSessionTimeout(mySessionManager.DEFAULT_GLOBAL_SESSION_TIMEOUT);
		mySessionManager.setSessionIdUrlRewritingEnabled(false);
		mySessionManager.setSessionDAO(redisSessionDAO);
		return mySessionManager;
	}

	/**
	 * 创建安全管理器对象,关联自定义Realm
	 * @return
	 */
	@Bean
	public DefaultWebSecurityManager securityManager(SessionManager sessionManager, RedisCacheManager redisCacheManager) {
		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
		securityManager.setRealm(realm());
		securityManager.setSessionManager(sessionManager);
		securityManager.setCacheManager(redisCacheManager);
		return securityManager;
	}

	/**
	 * 开启aop注解支持
	 * @param securityManager
	 * @return
	 */
	@Bean
	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
		return authorizationAttributeSourceAdvisor;
	}

	/**
	 * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),
	 * 需借助SpringAOP扫描使用Shiro注解的类,并在必要时进行安全逻辑验证
	 * @return
	 */
	@Bean
	@DependsOn("lifecycleBeanPostProcessor")
	public static DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		DefaultAdvisorAutoProxyCreator creator = new DefaultAdvisorAutoProxyCreator();
		creator.setProxyTargetClass(true);
		return creator;
	}

}
